package com.bocloud.cmp.service.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.common.enums.PostDataFormat;
import com.bocloud.common.http.ExtendHttpClient;
import com.bocloud.common.http.HttpClient;
import com.bocloud.common.model.BaseResult;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.model.Result;
import com.bocloud.common.ssh.SSH;
import com.mashape.unirest.http.Headers;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

/**
 * 仓库api接口
 * 
 * @author zjm
 * @date 2017年5月4日
 */
public class RegistryUtil {

	private static Logger logger = LoggerFactory.getLogger(RegistryUtil.class);
	private static final String HTTP = "http://";
	private static final String version = "/v2/";

	/**
	 * 按照镜像名称和版本号查看镜像详情
	 * 
	 * @author zjm
	 * @date 2017年3月30日
	 *
	 * @param address
	 * @param port
	 * @param name
	 * @param version
	 * @return
	 */
	public static BsmResult getSoftwareDetailByNameAndVersion(String address, int port, String name, String version,
			HttpClient client) {
		client.setDataFormat(PostDataFormat.RAW);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("Keep-Alive", "10");
		String url = "http://" + address + ":" + port + "/v2/" + name + "/manifests/" + version;
		Result resultMessage = client.get(map, null, url);
		if (resultMessage.isSuccess()) {
			return new BsmResult(true, resultMessage.getMessage(), "获取镜像信息成功");
		}
		logger.warn("仓库中不包含" + name + ":" + version + "镜像！");
		return new BsmResult(false, "仓库中不包含" + name + ":" + version + "镜像！");
	}

	/**
	 * 按照镜像名称和版本号查询digest
	 * 
	 * @author zjm
	 * @date 2017年5月4日
	 *
	 * @param address
	 * @param port
	 * @param name namespace+name
	 * @param version
	 * @return
	 */
	public static BsmResult getSoftwareDigestByNameAndVersion(String address, int port, String name, String version,
			ExtendHttpClient client) {
		try {
			Map<String, String> header = new HashMap<>();
			header.put("Accept", "application/vnd.docker.distribution.manifest.v2+json");
			String url = "http://" + address + ":" + port + "/v2/" + name + "/manifests/" + version;
			HttpResponse<com.mashape.unirest.http.JsonNode> response = Unirest.get(url).headers(header).asJson();
			if (response.getStatus() == 200) {
				Headers headers = response.getHeaders();
				if (headers.toString().contains("Docker-Content-Digest")) {
					List<String> list = headers.get("Docker-Content-Digest");
					String digest = list.get(0);
					logger.debug("获取镜像[" + name + ":" + version + "]的digest成功,digest:"
							+ digest.substring(digest.indexOf(":") + 1));
					return new BsmResult(true, digest.substring(digest.indexOf(":") + 1), "获取镜像信息成功");
				} else {
					logger.warn("未获取[" + name + ":" + version + "]镜像信息！");
					return new BsmResult(false, "未获取[" + name + ":" + version + "]镜像信息！");
				}
			}
			logger.warn("仓库中不包含" + name + ":" + version + "镜像！");
			return new BsmResult(false, "仓库中不包含" + name + ":" + version + "镜像！");
		} catch (Exception e) {
			logger.info("与服务端获取连接失败");
			return new BsmResult(false, "与服务端获取连接失败");
		}
	}

	/**
	 * 按照镜像名称和版本号删除镜像
	 * 
	 * @author zjm
	 * @date 2017年5月4日
	 *
	 * @param address
	 * @param port
	 * @param name
	 * @param digest
	 * @return
	 */
	public static BsmResult deleteSoftwareByNameAndDigest(String address, int port, String name, String digest,
			HttpClient client) {
		client.setDataFormat(PostDataFormat.RAW);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("Keep-Alive", "10");
		String url = "http://" + address + ":" + port + "/v2/" + name + "/manifests/" + digest;
		Result resultMessage = client.delete(map, null, url);
		if (resultMessage.isSuccess()) {
			return new BsmResult(true, resultMessage.getMessage(), "获取镜像信息成功");
		}
		logger.warn("删除" + name + "镜像失败！" + resultMessage.getMessage());
		return new BsmResult(false, "删除" + name + "镜像失败！" + resultMessage.getMessage());
	}

	/**
	 * 获取仓库的镜像名
	 * 
	 * @param ip
	 * @param port
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static BaseResult getImageNames(String url) {
		try {
			List<String> imageNamesList = new ArrayList<String>();
			url = "http://" + url + "/v2/_catalog";
			HttpResponse<com.mashape.unirest.http.JsonNode> response = Unirest.get(url).asJson();
			if (response.getStatus() == 200) {
				JSONObject object = JSONObject.parseObject(response.getBody().toString());
				JSONArray repositories = object.getJSONArray("repositories");
				Iterator<Object> iterator = repositories.iterator();
				while (iterator.hasNext()) {
					String nameObject = (String) iterator.next();
					if (!nameObject.contains("/")) {
						nameObject = "/" + nameObject;
					}
					imageNamesList.add(nameObject);
				}
				return new BaseResult(true, "获取成功", imageNamesList);
			} else {
				logger.error("连接仓库[" + url + "]出现异常，获取仓库镜像名称失败");
				return new BaseResult(false, "获取失败", null);
			}
		} catch (Exception e) {
			logger.info("与服务端获取连接失败");
			return new BaseResult(false, "与服务端获取连接失败");
		}
	}

	/**
	 * 获取仓库镜像下的tag
	 * 
	 * @param ip
	 * @param port
	 * @param imageName
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static BaseResult getImageTags(String url, String imageName) {
		try {
			url = "http://" + url + "/v2/" + imageName + "/tags/list";
			HttpResponse<com.mashape.unirest.http.JsonNode> response = Unirest.get(url).asJson();
			if (response.getStatus() != 200) {
				logger.error("连接仓库[" + url + "]出现异常，获取仓库镜像[" + imageName + "]的tag失败");
				return new BaseResult(false, "获取失败", null);
			}
			JSONObject jsonObject = JSONObject.parseObject(response.getBody().toString());
			JSONArray tags = jsonObject.getJSONArray("tags");
			return new BaseResult(true, "获取成功", tags);
		} catch (Exception e) {
			logger.info("与服务端获取连接失败");
			return new BaseResult(false, "与服务端获取连接失败");
		}
	}

	/**
	 * 获取镜像uuid
	 * 
	 * @param url
	 * @param imageName
	 * @param tag
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static BaseResult getUuid(String url, String imageName, String tag, HttpClient client) {
		client.setDataFormat(PostDataFormat.RAW);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("Keep-Alive", "10");
		url = "http://" + url + "/v2/" + imageName + "/manifests/" + tag;
		Result resultMessage = client.get(map, null, url);
		if (!resultMessage.isSuccess()) {
			logger.error("连接仓库[" + url + "]出现异常，获取仓库镜像[" + imageName + "]的Uuid失败");
			return new BaseResult(false, "获取失败", null);
		}
		JSONObject jsonObject = JSONObject.parseObject(resultMessage.getMessage().toString());
		JSONObject history = JSONObject.parseObject(jsonObject.getJSONArray("history").get(0).toString());
		JSONObject v1Compatibility = JSONObject.parseObject(history.getString("v1Compatibility"));
		String id = v1Compatibility.getString("id");
		return new BaseResult(true, "获取成功", id);
	}

	/**
	 * 用户名和密码检测
	 * 
	 * @param masterIp
	 * @param username
	 * @param password
	 * @return
	 */
	public static BsmResult checkUsernameWithPassword(String masterIp, String username, String password) {
		try {
			SSH ssh = new SSH(masterIp, username, password);
			if (ssh.connect()) {
				return new BsmResult(true, "可以使用");
			} else {
				return new BsmResult(false, "用户名或密码输入有错!");
			}
		} catch (Exception e) {
			logger.error("master ip、username、password check exception!", e);
			return new BsmResult(false, "Master username、password 输入有错!");
		}
	}

	/**
	 * 仓库状态检测
	 * 
	 * @param url
	 * @return
	 */
	public static Result checkRegistry(String url, HttpClient client) {
		try {
			url = HTTP + url + version;
			HttpResponse<com.mashape.unirest.http.JsonNode> response = Unirest.get(url).asJson();
			if (response.getStatus() == 200) {
				return new Result(true, response.getBody().toString());
			}
			return new Result(false, response.getBody().toString());
		} catch (Exception e) {
			logger.info("与服务端获取连接失败");
			return new Result(false, "与服务端获取连接失败");
		}
	}
}
